package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_CREATE_TIME;
import static com.tianji.common.constants.Constant.DATA_FIELD_NAME_LIKED_TIME;
import static com.tianji.common.constants.MqConstants.Exchange.LEARNING_EXCHANGE;
import static com.tianji.common.constants.MqConstants.Key.WRITE_REPLY;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author wxh
 * @since 2024-08-25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final IInteractionQuestionService questionService;
    private final RabbitMqHelper mqHelper;
    private final UserClient userClient;
    private final RemarkClient remarkClient;

    /**
     * 新增回答或评论接口  实战 4
     *
     * @param replyDTO 新增的回答或评论参数
     */
    @Override
    @Transactional
    public void addReply(ReplyDTO replyDTO) {
        if (ObjectUtil.isEmpty(replyDTO.getAnswerId()) && ObjectUtil.isEmpty(replyDTO.getQuestionId())) {
            throw new RuntimeException("问题id和回答id不能同时为空");
        }
        //1.对象拷贝
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        //2.直接新增
        reply.setUserId(UserContext.getUser());
        boolean save = save(reply);
        //3.判断返回的结果
        if (!save) {
            log.info("新增回答或评论失败");
        }
        boolean isAnswer = replyDTO.getAnswerId() == null;
        //4.如果是回答修改问题表最近一次回答id，并累加问题表的回答次数
        //4.1回答
        if (isAnswer) {
            if (ObjectUtil.isEmpty(replyDTO.getTargetReplyId())) {
                questionService.lambdaUpdate()
                        .eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                        .eq(replyDTO.getIsStudent(), InteractionQuestion::getStatus, QuestionStatus.UN_CHECK.getValue())
                        .setSql(isAnswer, "answer_times = answer_times + 1")
                        .set(InteractionQuestion::getLatestAnswerId, reply.getId())
                        .update();
            }

        }
        //5.不是回答则累加回答下的评论次数
        if (!isAnswer) {
            this.lambdaUpdate()
                    .eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .setSql("reply_times = reply_times +1")
                    .update();
        }
        //6.回复之后发消息
        try {
            log.info("开始发送回复积分消息");
            mqHelper.send(LEARNING_EXCHANGE, WRITE_REPLY, UserContext.getUser());
        } catch (Exception e) {
            log.error("写回复发送新增积分消息失败：{}", e);
        }
    }


    /**
     * 分页查询回答或评论列表  实战 3
     *
     * @param replyPageQuery
     * @return
     */
    @Override
    public PageDTO<ReplyVO> queryReply(ReplyPageQuery replyPageQuery, boolean isStudent) {
        //1.判断参数条件
        if (ObjectUtil.isEmpty(replyPageQuery.getQuestionId()) &&
                ObjectUtil.isEmpty(replyPageQuery.getAnswerId())) {
            throw new RuntimeException("问题id和回答id不能同时为空");
        }
        //2.分页查询relay表
        //select * from interaction_reply where question_id = 1585089140469317634 and answer_id = 1585178277083951106
        //and user_id = 129 and  hidden = 0 order by create_time desc limit 0,10
        Page<InteractionReply> replyPage = this.lambdaQuery()
                .eq(ObjectUtil.isNotEmpty(replyPageQuery.getQuestionId()), InteractionReply::getQuestionId, replyPageQuery.getQuestionId())
                .eq(InteractionReply::getAnswerId, BooleanUtils.isTrue(ObjectUtil.isEmpty(replyPageQuery.getAnswerId())) ? 0L : replyPageQuery.getAnswerId())
                .eq(isStudent, InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPage(
                        new OrderItem(DATA_FIELD_NAME_LIKED_TIME, false),
                        new OrderItem(DATA_FIELD_NAME_CREATE_TIME, false)));
        List<InteractionReply> records = replyPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            //2.0查询的分页数据为空，返回一个空集合
            return PageDTO.empty(replyPage);
        }
        //2.1准备收集回答的userId、评论的目标userId
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> targetUserIds = new HashSet<>();
        //2.2收集用户对业务点赞的id
        Set<Long> bizIds = new HashSet<>(records.size());
        for (InteractionReply record : records) {
            if (!isStudent || !record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            targetUserIds.add(record.getTargetUserId());
            bizIds.add(record.getId());
        }
        targetUserIds.remove(0L);
        targetUserIds.remove(null);
        if (targetUserIds.size() > 0) {
            userIds.addAll(targetUserIds);
        }
        //3.查询用户信息、目标用户的信息(回答或评论的id) targetUserName 用 targetUserId查询
        Map<Long, UserDTO> userInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(userIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userInfoMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }
        if (ObjectUtil.isEmpty(userInfoMap)) {
            throw new RuntimeException("用户信息Map出错");
        }
        //4.调用查询点赞状态Feign接口
        Set<Long> likeStatus = remarkClient.isLikeStatusAndUser(bizIds);

        //6.遍历分页的结果进行数据分装
        List<ReplyVO> voList = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            //6.1属性拷贝
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);
            //6.2分装当前用户信息
            UserDTO userDTO = userInfoMap.get(record.getUserId());
            //6.3无论是回答还是回复都要分昵称判断是否为回答
            if (!isStudent || !record.getAnonymity()) {
                vo.setUserName(userDTO.getName());
                vo.setUserIcon(userDTO.getIcon());
            }
            //判断为一级评论
            if (record.getTargetReplyId() != null) {
                //6.4给目标用户分装昵称
                UserDTO targetUserDTO = userInfoMap.get(record.getTargetUserId());
                vo.setTargetUserName(targetUserDTO.getName());
            }
            //6.5装当前用户是否点过赞
            if (likeStatus.contains(record.getId()) && ObjectUtil.isNotEmpty(likeStatus)) {
                vo.setLiked(true);
            }
            //6.6将vo添加至volist
            voList.add(vo);
        }
        //7.返回volist
        return PageDTO.of(replyPage, voList);
    }
}
